package cn.wjzhang.middle.modules.global.beans.request;

import cn.hutool.core.lang.TypeReference;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.wjzhang.core.exception.BootException;
import cn.wjzhang.middle.factory.SeniverseFactory;
import cn.wjzhang.middle.modules.global.beans.request.BaseRequest;
import com.alibaba.csp.sentinel.cluster.annotation.RequestType;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.beans.factory.annotation.Value;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.HashMap;
import java.util.Map;

/**
 * ========================
 * 心知天气
 *
 * @author wjzhang
 * @version v1.0
 * ========================
 * @date 2023/7/3 9:55
 */
@EqualsAndHashCode(callSuper = true)
@Data
public abstract class SeniverseRequest<T> extends BaseRequest {


    @JSONField(serialize = false)
    private String url;

    @JSONField(serialize = false)
    private cn.hutool.http.Method requestType;

    /**
     * 常规请求
     *
     * @return 响应
     * @throws BootException 自定义异常
     */
    public T execute() throws BootException {
        // 获取url和requestType
        try {
            Method build = this.getClass().getMethod("build");
            build.invoke(this);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            throw new BootException("build方法不存在", e);
        }

        // 获取参数
        String params = JSONObject.toJSONString(this);
        JSONObject jsonParams = JSON.parseObject(params);
        jsonParams.put("key", SeniverseFactory.getKey());

        // 请求地址
        String requestUrl = SeniverseFactory.getHost() + url;

        // 包装HTTP请求参数
        HttpRequest httpRequest = HttpRequest.of(requestUrl)
                // 设置请求头
                .header("Content-Type", "application/json")
                // 设置请求类型
                .contentType("application/json")
                .method(requestType);

        // 设置参数
        if (cn.hutool.http.Method.GET == requestType){
            httpRequest.form(jsonParams);
        } else {
            httpRequest.body(jsonParams.toJSONString());
        }
        // 发送请求
        HttpResponse resp = httpRequest.execute();

        // 获取响应状态码和响应体
        int status = resp.getStatus();
        String resCtx = resp.body();

        Class<T> clazz = extractGenericClass();
        T response;
        try {
            response = (T) JSON.parseObject(resCtx, clazz);

            Method setStatus = clazz.getMethod("setStatus", int.class);
            setStatus.invoke(response, status);
            Method setBody = clazz.getMethod("setBody", String.class);
            setBody.invoke(response, resCtx);
        } catch (JSONException e) {
            try {
                response = clazz.newInstance();
                Method setBody = clazz.getMethod("setBody", String.class);
                setBody.invoke(response, resCtx);
            } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException ex) {
                throw new BootException("响应对象不能实例化", ex);
            }
        }
        catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
            throw new BootException("响应对象操作失败", ex);
        }

        return response;
    }

    private Class<T> extractGenericClass() {
        ParameterizedType ptype = (ParameterizedType) this.getClass().getGenericSuperclass();
        return (Class<T>) ptype.getActualTypeArguments()[0];
    }


    public abstract void build();
}
